package com.myblog.adkblog.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;
import java.util.function.BiFunction;

/**
 * Mybatis批量插入工具类
 * 日期: 2024年10月24日
 * 时间: 17:37
 * 作者: XinForever
 */
@Component
@Slf4j
public class MyBatisUtils {

    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    private static final int DEFAULT_BATCH_SIZE = 500;
    /**
     * 批量插入数据的方法
     *
     * @param <T> 数据类型
     * @param <U> 映射器类型
     * @param <R> 结果类型
     * @param data 需要插入的数据列表
     * @param mapperClass 映射器类
     * @param func 处理函数
     * @return 插入成功的记录数
     */
    public <T,U,R> int batchInsertFunc(List<T> data, Class<U> mapperClass, BiFunction<T,U,R> func,Integer batchSize){
        if (CollectionUtils.isEmpty(data)){
            throw new IllegalArgumentException("数据为空！");
        }
        if (Objects.isNull(batchSize)){
            batchSize = DEFAULT_BATCH_SIZE;
        }
        try {
            SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
            List<List<T>> partition = ListUtils.partition(data, batchSize);
            U mapper = sqlSession.getMapper(mapperClass);
            for (List<T> list : partition) {
                list.forEach(item-> func.apply(item,mapper));
            }
            sqlSession.commit();
        }catch (Exception e){
            log.error("批量插入数据失败：{}",e.getMessage());
            throw new RuntimeException("批量插入数据失败", e);
        }
        return data.size();
    }

}
